// =============================================
// 结构体名称：SmallXXHash
// 类型：readonly struct（不可变，线程安全，高性能）
// 用途：一个轻量级、快速的、非加密的哈希函数，支持链式调用（.Eat()），
//       用于将输入数据（如整数、字节）逐步混入哈希状态，最终生成一个高质量的 uint 哈希值。
//       常用于程序化生成、哈希表、数据指纹、唯一标识等场景。
// =============================================

public readonly struct SmallXXHash
{
	// --------------------------------------------------------------------------
	// 【常量定义】：五个大质数，用于哈希计算中的乘法与混淆，提升雪崩效应
	// 这些是精心挑选的 32 位质数，用于与输入数据相乘，让哈希更“乱”、更均匀
	// --------------------------------------------------------------------------
	const uint primeA = 0b10011110001101110111100110110001; // 0x9E3779B1 的一种变种？实际值为一个大质数
	const uint primeB = 0b10000101111010111100101001110111; // 另一个大质数，用于最终雪崩步骤
	const uint primeC = 0b11000010101100101010111000111101; // 用于 Eat(int) 中的乘法混淆
	const uint primeD = 0b00100111110101001110101100101111; // 用于 Eat(int) 之后的乘法
	const uint primeE = 0b00010110010101100110011110110001; // 用于 Seed() 和 Eat(byte)

	// --------------------------------------------------------------------------
	// 【状态字段】：accumulator，哈希计算的核心状态值
	// 它累积了所有通过 .Eat() 方法“喂入”的数据，是最终生成哈希值的基础
	// --------------------------------------------------------------------------
	readonly uint accumulator;

	// --------------------------------------------------------------------------
	// 【构造函数】：用给定的累加值（accumulator）初始化一个 SmallXXHash 实例
	// --------------------------------------------------------------------------
	public SmallXXHash(uint accumulator)
	{
		this.accumulator = accumulator;
	}

	// --------------------------------------------------------------------------
	// 【隐式转换：从 uint 到 SmallXXHash】
	// 允许你直接将一个 uint 赋值给 SmallXXHash，比如：SmallXXHash hash = 123u;
	// --------------------------------------------------------------------------
	public static implicit operator SmallXXHash(uint accumulator) =>
		new SmallXXHash(accumulator);

	// --------------------------------------------------------------------------
	// 【静态方法：Seed(int seed)】
	// 用途：为哈希函数设置一个初始种子值，返回一个 SmallXXHash 实例
	//      这是你开始哈希计算的起点，通常传入一个 int 类型的随机种子
	// --------------------------------------------------------------------------
	public static SmallXXHash Seed(int seed) =>
		(uint)seed + primeE; // 将种子转为 uint 并加上一个质数 primeE，作为初始 accumulator

	// --------------------------------------------------------------------------
	// 【工具函数：RotateLeft】
	// 作用：对一个 uint 值执行“循环左移”操作，移位位数由 steps 指定
	// 循环左移是哈希函数中常用的位操作，用于比特扩散
	// --------------------------------------------------------------------------
	static uint RotateLeft(uint data, int steps) =>
		(data << steps) | (data >> 32 - steps); // 左移 steps 位，并将移出的高位补到右侧

	// --------------------------------------------------------------------------
	// 【方法：Eat(int data)】
	// 作用：将一个 32 位整数“喂入”哈希函数，更新内部的 accumulator 状态
	//      这是链式调用的核心方法之一，用于处理整数输入
	// --------------------------------------------------------------------------
	public SmallXXHash Eat(int data) =>
		RotateLeft(accumulator + (uint)data * primeC, 17) * primeD;
	// 步骤拆解：
	// 1. 将输入的 data 转为 uint，并乘以质数 primeC（用于混淆）
	// 2. 加到当前的 accumulator 上
	// 3. 循环左移 17 位（增加比特扰乱）
	// 4. 乘以另一个质数 primeD（进一步增强雪崩效应）
	// 5. 返回一个新的 SmallXXHash，其 accumulator 为上述计算结果

	// --------------------------------------------------------------------------
	// 【方法：Eat(byte data)】
	// 作用：将一个 8 位字节“喂入”哈希函数，更新状态
	//      用于处理字节流或小数据输入
	// --------------------------------------------------------------------------
	public SmallXXHash Eat(byte data) =>
		RotateLeft(accumulator + data * primeE, 11) * primeA;
	// 步骤拆解（类似 Eat(int)，但针对 byte 类型）：
	// 1. byte 转为数值，乘以 primeE
	// 2. 加到当前 accumulator
	// 3. 循环左移 11 位
	// 4. 乘以 primeA
	// 5. 返回新的 SmallXXHash

	// --------------------------------------------------------------------------
	// 【隐式转换：从 SmallXXHash 到 uint】
	// 作用：当你需要最终哈希值时（比如 uint 类型），调用此转换
	//      在转换时会先对当前的 accumulator 进行“雪崩处理”，
	//      让每一位都充分影响最终结果的每一位，提升哈希质量
	// --------------------------------------------------------------------------
	public static implicit operator uint(SmallXXHash hash)
	{
		uint avalanche = hash.accumulator; // 取当前的累加值

		// 下面是经典的“雪崩处理”步骤，让输入微变 → 输出巨变
		avalanche ^= avalanche >> 15; // 右移 15 位后异或，扩散高位影响
		avalanche *= primeB;          // 乘以质数，进一步混淆
		avalanche ^= avalanche >> 13; // 再次右移异或
		avalanche *= primeC;          // 再次乘以质数
		avalanche ^= avalanche >> 16; // 最后一次右移异或

		return avalanche; // 返回经过雪崩处理后的最终哈希值
	}
}